package com.foreveross.proxyip.infra.db.mongo;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.foreveross.proxyip.infra.db.mongo.annotation.MongoTable;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;


/**
 * mongo 仓储接口
 * 
 * @author fb
 */
public class MongoRepositoryImpl implements IMongoRepository{
	
	private static Logger logger = LoggerFactory.getLogger(MongoManager.class);
	
	private MongoClient client = MongoManager.instance().getMongoClient();
	
	private DB db;
	
	public MongoRepositoryImpl(String database) {
		this.db = client.getDB(database);
	}
	
	@Override
	public synchronized void createCollection(String collection, DBObject options) {
		db.createCollection(collection, options);
	}

	@Override
	public <T> void save(T data) {
		String table =  getTable(data.getClass());
		
		if (table == null) {
			logger.error("mongo持久异常，bean[{}]中没有指定表名", data.getClass().getName());
			return;
		}
		
		DBCollection coll = db.getCollection(table);
		DBObject bdb;
		
		try {
			bdb = MongoReflectUtils.createDBObject(data);
			coll.insert(bdb);
		} catch (Exception e) {
			logger.error("保存数据时出错：", e);
		}
	}

	@Override
	public <T> void save(List<T> datas) {
		if (datas.isEmpty()) {
			return;
		}
		
		String table =  getTable(datas.get(0).getClass());
		
		if (table == null) {
			logger.error("mongo持久异常，bean[{}]中没有指定表名", datas.get(0).getClass().getName());
			return;
		}
		
		DBCollection coll = db.getCollection(table);
		List<DBObject> bdbs = new ArrayList<DBObject>();
		
		try {
			for (int i = 0; i < datas.size(); i++) {
				bdbs.add(MongoReflectUtils.createDBObject(datas.get(i)));
				if (i%1000 == 0) {
					coll.insert(bdbs);
					bdbs.clear();
				}
			}
			coll.insert(bdbs);
		} catch (Exception e) {
			logger.error("保存数据时出错：", e);
		}
	}

	@Override
	public <T> List<DBObject> query(Class<T> clazz, BasicDBObject query) {
		String table =  getTable(clazz);
		DBCollection coll = db.getCollection(table);
		DBCursor dbc = coll.find(query);
		List<DBObject> joList = new ArrayList<DBObject>();
		
        while (dbc.hasNext()) {
            DBObject jo = dbc.next();
            joList.add(jo);
        }
        
		return joList;
	}

	private <T> String getTable(Class<T> clazz) {
		MongoTable tableAn = clazz.getAnnotation(MongoTable.class);
		
		if (tableAn == null || StringUtils.isEmpty(tableAn.value())) {
			return null;
		}
		
		return tableAn.value().trim();
	}
}
